package com.imooc.controller;


import com.imooc.enums.VideoStatusEnum;
import com.imooc.pojo.Bgm;
import com.imooc.pojo.Comments;
import com.imooc.pojo.Videos;
import com.imooc.service.BgmService;
import com.imooc.service.VideoService;
import com.imooc.utils.FFMPEGUtils;
import com.imooc.utils.IMoocJSONResult;
import com.imooc.utils.PagedResult;
import com.imooc.utils.PagedResultUtils;
import io.swagger.annotations.*;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * @author Zhou
 * @create 2020-11-13 12:16
 */
@RestController
@RequestMapping("/video")
@Api(value = "视频相关业务的接口", tags = {"视频相关业务的controller"})
public class VideoController extends BasicController {
    @Autowired
    private BgmService bgmService;
    @Autowired
    private VideoService videoService;

    @Transactional
    @ApiOperation(value = "用户上传视频", notes = "用户上传视频的接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户Id", required = true, dataType = "String", paramType = "form"),
            @ApiImplicitParam(name = "bgmId", value = "背景音乐Id", required = false, dataType = "String", paramType = "form"),
            @ApiImplicitParam(name = "videoSeconds", value = "背景音乐播放时长", required = true, dataType = "String", paramType = "form"),
            @ApiImplicitParam(name = "videoWidth", value = "视频宽度", required = true, dataType = "String", paramType = "form"),
            @ApiImplicitParam(name = "videoHeight", value = "视频高度", required = true, dataType = "String", paramType = "form"),
            @ApiImplicitParam(name = "desc", value = "视频描述信息", required = false, dataType = "String", paramType = "form"),
    })
    @PostMapping(value = "/upload", headers = {"content-type=multipart/form-data"})
    public IMoocJSONResult upload(String userId,
                                  String bgmId,
                                  double videoSeconds,
                                  int videoWidth,
                                  int videoHeight,
                                  String desc,
                                  @ApiParam(value = "短视频", required = true) MultipartFile file) throws IOException {

        if (StringUtils.isEmpty(userId)) {
            return IMoocJSONResult.errorMsg("用户id不能为空");
        }

        //保存到数据库中的相对路径
        String uploadPathDB = "/" + userId + "/video";

        String coverPathDB = "/" + userId + "/video";

        //输入输出流
        FileOutputStream fileOutputStream = null;
        InputStream inputStream = null;

        //文件上传的最终保存路径
        String finalVideoPath = "";

        try {
            if (file != null) {
                String filename = file.getOriginalFilename();

                String arrayFilenameItem[] = filename.split("\\.");
                String fileNamePrefix = "";
                for (int i = 0 ; i < arrayFilenameItem.length-1 ; i ++) {
                    fileNamePrefix += arrayFilenameItem[i];
                }
//                String fileNamePrefix = filename.split("\\.")[0];

                if (!StringUtils.isEmpty(filename)) {

                    finalVideoPath = FILESPACE + uploadPathDB + "/" + filename;

                    //设置数据库保存路径
                    uploadPathDB += ("/" + filename);
                    coverPathDB = coverPathDB + "/" + fileNamePrefix + ".jpg";

                    File outFile = new File(finalVideoPath);
                    if (outFile.getParentFile() != null || !outFile.getParentFile().isDirectory()) {
                        //创建父文件夹
                        outFile.getParentFile().mkdirs();
                    }

                    fileOutputStream = new FileOutputStream(outFile);
                    inputStream = file.getInputStream();
                    IOUtils.copy(inputStream, fileOutputStream);
                }
            } else {
                return IMoocJSONResult.errorMsg("上传出错");
            }
        } catch (IOException e) {
            e.printStackTrace();
            return IMoocJSONResult.errorMsg("上传出错");
        } finally {
            if (fileOutputStream != null) {
                //这个方法的作用是把缓冲区的数据强行输出。调用flush是保证缓存清空输出
                fileOutputStream.flush();
                fileOutputStream.close();
            }
            if (inputStream != null) {
                inputStream.close();
            }
        }

        // 判断bgmId是否为空，如果不为空，那就查询bgm的信息，并且合并视频生成新的视频
        if (!StringUtils.isEmpty(bgmId)) {
            Bgm bgm = bgmService.queryBgmById(bgmId);
            String mp3InputPath = FILESPACE + bgm.getPath();

            FFMPEGUtils tool = new FFMPEGUtils(FFMPEGEXE, NOVIDEOOUTPUTPATH);

            String videoOutputName = UUID.randomUUID().toString() + ".mp4";
            String videoInputPath = finalVideoPath;
            uploadPathDB = "/" + userId + "/video" + "/" + videoOutputName;
            finalVideoPath = FILESPACE + uploadPathDB;
            //加背景音
            tool.convert(videoInputPath, mp3InputPath, finalVideoPath, videoSeconds);


            //对视频进行截图
            tool.getCoverFromVideo(finalVideoPath, FILESPACE + coverPathDB);
        }

        //删除无背景音乐，此处有bug
        File file1 = new File(NOVIDEOOUTPUTPATH);
        file1.delete();
//        int tryCount = 0;
//        while(tryCount++ <10)
//        {
//            System.gc();
//            file1.delete();
//        }


        // 保存视频信息到数据库
        Videos video = new Videos();
        video.setAudioId(bgmId);
        video.setUserId(userId);
        video.setVideoSeconds((float) videoSeconds);
        video.setVideoHeight(videoHeight);
        video.setVideoWidth(videoWidth);
        video.setVideoDesc(desc);
        video.setVideoPath(uploadPathDB);
        video.setCoverPath(coverPathDB);
        video.setStatus(VideoStatusEnum.SUCCESS.value);
        video.setCreateTime(new Date());

        String videoId = videoService.saveVideo(video);

        return IMoocJSONResult.ok(videoId);
    }

    @ApiOperation(value = "上传视频封面", notes = "上传视频封面的接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "videoId", value = "视频主键Id", required = true, dataType = "String", paramType = "form"),
            @ApiImplicitParam(name = "userId", value = "用户Id", required = true, dataType = "String", paramType = "form")
    })
    @PostMapping(value = "/uploadCover")
    public IMoocJSONResult uploadCover(String videoId, String userId,
                                       @ApiParam(value = "视频封面", required = true) MultipartFile file) throws IOException {
        if (StringUtils.isEmpty(videoId) || StringUtils.isEmpty(userId)) {
            return IMoocJSONResult.errorMsg("视频主键或者用户id不能为空");
        }

        //保存到数据库中的相对路径
        String uploadPathDB = "/" + userId + "/video";

        //输入输出流
        FileOutputStream fileOutputStream = null;
        InputStream inputStream = null;

        //文件上传的最终保存路径
        String finalCoverPath = "";

        try {
            if (file != null) {
                String filename = file.getOriginalFilename();
                if (!StringUtils.isEmpty(filename)) {

                    finalCoverPath = FILESPACE + uploadPathDB + "/" + filename;

                    //设置数据库保存路径
                    uploadPathDB += ("/" + filename);

                    File outFile = new File(finalCoverPath);
                    if (outFile.getParentFile() != null || !outFile.getParentFile().isDirectory()) {
                        //创建父文件夹
                        outFile.getParentFile().mkdirs();
                    }

                    fileOutputStream = new FileOutputStream(outFile);
                    inputStream = file.getInputStream();
                    IOUtils.copy(inputStream, fileOutputStream);
                }
            } else {
                return IMoocJSONResult.errorMsg("上传出错");
            }
        } catch (IOException e) {
            e.printStackTrace();
            return IMoocJSONResult.errorMsg("上传出错");
        } finally {
            if (fileOutputStream != null) {
                //这个方法的作用是把缓冲区的数据强行输出。调用flush是保证缓存清空输出
                fileOutputStream.flush();
                fileOutputStream.close();
            }
            if (inputStream != null) {
                inputStream.close();
            }
        }

        //保存封面信息到数据库
        videoService.UpdateVideo(videoId, uploadPathDB);
        return IMoocJSONResult.ok();
    }

    /**
     * 分页和搜索查询视频列表
     *
     * @param videos
     * @param isSaveRecord：1：需要保存，0,：不需要保存，或者为空的时候
     * @param page
     * @return
     */
    @ApiOperation(value = "查询视频", notes = "查询视频的接口")
    @ApiImplicitParam(name = "page", value = "查询的页码", required = true, dataType = "Integer", paramType = "query")
    @PostMapping(value = "/showAll")
    public IMoocJSONResult showAll(@RequestBody Videos videos, Integer isSaveRecord, Integer page, Integer pageSize) {
        if (page == null) {
            page = 1;
        }

        if (pageSize == null) {
            pageSize = PAGESIZE;
        }

        PagedResultUtils allVideos = videoService.getAllVideos(videos, isSaveRecord, page, pageSize);

        return IMoocJSONResult.ok(allVideos);
    }

    /**
     * 热搜词的排序查询
     *
     * @return
     */
    @ApiOperation(value = "查询热搜", notes = "查询热搜的接口")
    @PostMapping(value = "/hot")
    public IMoocJSONResult hot() {
        return IMoocJSONResult.ok(videoService.getHotWords());
    }

    @ApiImplicitParams({
            @ApiImplicitParam(name = "videoId", value = "视频主键Id", required = true, dataType = "String", paramType = "form"),
            @ApiImplicitParam(name = "userId", value = "用户Id", required = true, dataType = "String", paramType = "form"),
            @ApiImplicitParam(name = "videoCreateId", value = "视频所有者Id", required = true, dataType = "String", paramType = "form")
    })
    @ApiOperation(value = "点赞", notes = "用户点赞的接口")
    @PostMapping(value = "/userLike")
    public IMoocJSONResult userLike(String userId, String videoId, String videoCreateId) {
        videoService.userLikeVideo(userId, videoId, videoCreateId);
        return IMoocJSONResult.ok();
    }

    @ApiImplicitParams({
            @ApiImplicitParam(name = "videoId", value = "视频主键Id", required = true, dataType = "String", paramType = "form"),
            @ApiImplicitParam(name = "userId", value = "用户Id", required = true, dataType = "String", paramType = "form"),
            @ApiImplicitParam(name = "videoCreateId", value = "视频所有者Id", required = true, dataType = "String", paramType = "form")
    })
    @ApiOperation(value = "取消点赞", notes = "用户取消点赞的接口")
    @PostMapping(value = "/userUnlike")
    public IMoocJSONResult userUnlike(String userId, String videoId, String videoCreateId) {
        videoService.userUnlikeVideo(userId, videoId, videoCreateId);
        return IMoocJSONResult.ok();
    }

    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "视频主键Id", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "page", value = "分页的页面", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "pageSize", value = "分页的大小", required = false, dataType = "String", paramType = "query")
    })
    @ApiOperation(value = "查询收藏用户的视频", notes = "查询收藏用户的视频的接口")
    @PostMapping(value = "/showMyLike")
    public IMoocJSONResult showMyLike(String userId, Integer page, Integer pageSize) {
        if (StringUtils.isEmpty(userId)) {
            return IMoocJSONResult.ok();
        }

        if (page == null) {
            page = 1;
        }

        if (pageSize == null) {
            pageSize = PAGESIZE;
        }

        PagedResult videosList = videoService.queryMyLikeVideos(userId, page, pageSize);
        return IMoocJSONResult.ok(videosList);
    }

    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "视频主键Id", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "page", value = "分页的页面", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "pageSize", value = "分页的大小", required = false, dataType = "String", paramType = "query")
    })
    @ApiOperation(value = "查询关注用户的视频", notes = "查询关注用户的视频的接口")
    @PostMapping(value = "/showMyFollow")
    public IMoocJSONResult showMyFollow(String userId, Integer page, Integer pageSize) {
        if (StringUtils.isEmpty(userId)) {
            return IMoocJSONResult.ok();
        }

        if (page == null) {
            page = 1;
        }

        if (pageSize == null) {
            pageSize = PAGESIZE;
        }

        PagedResult videosList = videoService.queryMyFollowVideos(userId, page, pageSize);
        return IMoocJSONResult.ok(videosList);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @ApiOperation(value = "保存评论", notes = "保存评论的接口")
    @PostMapping("/saveComment")
    public IMoocJSONResult saveComment(@RequestBody Comments comments, String fatherCommentId, String toUserId){
        if (! StringUtils.isEmpty(fatherCommentId)){
            comments.setFatherCommentId(fatherCommentId);
        }
        if (! StringUtils.isEmpty(toUserId)){
            comments.setToUserId(toUserId);
        }
        videoService.saveComment(comments);
        return IMoocJSONResult.ok();
    }

    @ApiImplicitParams({
            @ApiImplicitParam(name = "videoId", value = "视频的Id", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "page", value = "分页的页面", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "pageSize", value = "分页的大小", required = false, dataType = "String", paramType = "query")
    })
    @ApiOperation(value = "查询评论信息", notes = "查询评论信息的接口")
    @PostMapping(value = "/getVideoComments")
    public IMoocJSONResult getVideoComments(String videoId, Integer page, Integer pageSize) {
        if (StringUtils.isEmpty(videoId)) {
            return IMoocJSONResult.ok();
        }

        if (page == null) {
            page = 1;
        }

        if (pageSize == null) {
            pageSize = PAGESIZE;
        }

        PagedResult list = videoService.getAllComments(videoId, page, pageSize);
        return IMoocJSONResult.ok(list);
    }


}
